package cmd

import (
	"gitee.com/whilew/gmodel/internal/cfg"
	"gitee.com/whilew/gmodel/internal/util"
	"github.com/spf13/cobra"
	"strings"
)

var (
	envWithoutP = envWithoutCmd.Flags().BoolP("prefix", "p", false, "")
	envWithoutW = envWithoutCmd.Flags().BoolP("write", "w", false, "")
	envWithoutU = envWithoutCmd.Flags().BoolP("unset", "u", false, "")
	envWithoutC = envWithoutCmd.Flags().BoolP("clear", "c", false, "")
)

var envWithoutCmd = &cobra.Command{
	Use:   "without",
	Short: "without model",
}

func init() {
	envWithoutCmd.Run = envWithoutCmdRun
	envCmd.AddCommand(envWithoutCmd)
}

func envWithoutCmdRun(md *cobra.Command, args []string) {
	if *envWithoutU && *envWithoutW {
		util.Fatalf("gmodel: cannot use -u with -w")
	}

	if !*envWithoutU && !*envWithoutW && !*envWithoutC {
		util.Fatalf("gmodel: must use -u or -w or -c")
	}

	proj, err := util.GetProjRootDir()
	if err != nil {
		util.Fatalf("gmodel: get project root dir fail: %v", err)
	}
	if proj == "" {
		util.Fatalf("gmodel: must run int project dir")
	}

	if *envWithoutW {
		envWithoutWRun(args)
		return
	}

	if *envWithoutU {
		envWithoutURun(args)
		return
	}

	if *envWithoutC {
		updateEnvFile(nil, map[string]bool{
			cfg.EnvWithoutCfgKey:  true,
			cfg.EnvWithoutPCfgKey: true,
		})
		return
	}
}

func envWithoutWRun(args []string) {
	var key = cfg.EnvWithoutCfgKey
	if *envWithoutP {
		key = cfg.EnvWithoutPCfgKey
	}
	without := strings.Split(cfg.GetCfg(key), ",")
	if without[len(without)-1] == "" {
		without = without[:len(without)-1]
	}

	if len(args) <= 0 {
		util.Fatalf("gmodel: must input table name")
	}

	addwithout := strings.Split(args[0], ",")

	without = append(without, addwithout...)
	without = removeDuplication_map(without)

	updateEnvFile(map[string]string{
		key: strings.Join(without, ","),
	}, nil)
}
func envWithoutURun(args []string) {
	var key = cfg.EnvWithoutCfgKey
	if *envWithoutP {
		key = cfg.EnvWithoutPCfgKey
	}
	without := strings.Split(cfg.GetCfg(key), ",")
	if without[len(without)-1] == "" {
		without = without[:len(without)-1]
	}

	if len(args) <= 0 {
		util.Fatalf("gmodel: must input table name")
	}

	delwithout := strings.Split(args[0], ",")

	without = difference(without, delwithout)

	updateEnvFile(map[string]string{
		key: strings.Join(without, ","),
	}, nil)
}

func removeDuplication_map(arr []string) []string {
	set := make(map[string]struct{}, len(arr))
	j := 0
	for _, v := range arr {
		_, ok := set[v]
		if ok {
			continue
		}
		set[v] = struct{}{}
		arr[j] = v
		j++
	}
	return arr[:j]
}

// 求差集 slice1-并集
func difference(slice1, slice2 []string) []string {
	m := make(map[string]int)
	nn := make([]string, 0)
	inter := intersect(slice1, slice2)
	for _, v := range inter {
		m[v]++
	}

	for _, value := range slice1 {
		times, _ := m[value]
		if times == 0 {
			nn = append(nn, value)
		}
	}
	return nn
}

// 求交集
func intersect(slice1, slice2 []string) []string {
	m := make(map[string]int)
	nn := make([]string, 0)
	for _, v := range slice1 {
		m[v]++
	}

	for _, v := range slice2 {
		times, _ := m[v]
		if times == 1 {
			nn = append(nn, v)
		}
	}
	return nn
}
